package com.jyw.business.ins.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyw.business.ins.domain.InsPlan;
import com.jyw.business.ins.domain.InsPlanExecutionTime;
import com.jyw.business.ins.domain.InsPlanItem;
import com.jyw.business.ins.domain.dto.web.*;
import com.jyw.business.ins.domain.vo.web.*;
import com.jyw.business.ins.enums.EffectiveTypeEnum;
import com.jyw.business.ins.enums.InsPlanWeekEnum;
import com.jyw.business.ins.mapper.InsPlanMapper;
import com.jyw.business.ins.service.IInsPlanExecutionTimeService;
import com.jyw.business.ins.service.IInsPlanItemService;
import com.jyw.business.ins.service.IInsPlanService;
import com.jyw.business.ins.service.IInsTaskJobService;
import com.jyw.business.ins.task.InspectionTaskUtil;
import com.jyw.common.utils.DateUtils;
import com.jyw.common.utils.LocalTimeUtil;
import com.jyw.system.utils.ConversionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 巡检计划Service业务层处理
 *
 * @author zhangcheng
 * @date 2023-09-28
 */
@Service
public class InsPlanServiceImpl extends ServiceImpl<InsPlanMapper, InsPlan> implements IInsPlanService {
    @Resource
    private InsPlanMapper insPlanMapper;

    @Resource
    private IInsPlanItemService insPlanItemService;

    @Resource
    private IInsPlanExecutionTimeService insPlanExecutionTimeService;

    @Resource
    private IInsTaskJobService insTaskJobService;

    /**
     * 查询巡检计划
     *
     * @param id 巡检计划主键
     * @return 巡检计划
     */
    @Override
    public InsPlan selectInsPlanById(Long id) {
        return insPlanMapper.selectInsPlanById(id);
    }

    @Override
    public InsPlanInfoVO selectInfoPlanById(Long id) {
        InsPlanInfoVO insPlanInfoVO = insPlanMapper.findInsPlanInfo(id);
        if (insPlanInfoVO != null) {
            List<InsPlanExecutionTime> timeList = insPlanExecutionTimeService.selectByPlanId(id);
            if (CollectionUtil.isNotEmpty(timeList)) {
                insPlanInfoVO.setExecutionTimeList(timeList);
                List<String> stringList = new ArrayList<>();
                String pattern = "HH:mm";
                timeList.forEach(a -> {
                    if (a.getStartTime() != null && a.getEndTime() != null) {
                        String startTime = LocalTimeUtil.formatLocalTime(a.getStartTime(), pattern);
                        String endTime = LocalTimeUtil.formatLocalTime(a.getEndTime(), pattern);
                        String range = startTime + "-" + endTime;
                        stringList.add(range);
                    }
                });
                String executionTimeStr = stringList.stream().collect(Collectors.joining(","));
                insPlanInfoVO.setExecutionTimeStr(executionTimeStr);
            }
            List<InsPlanItemVO> itemList = insPlanItemService.getPlanItemList(id);
            if (CollectionUtil.isNotEmpty(itemList)) {
                insPlanInfoVO.setPlanItemList(itemList);
            }
            if (StrUtil.isNotEmpty(insPlanInfoVO.getWeekly())) {
                EnumSet<InsPlanWeekEnum> all = EnumSet.allOf(InsPlanWeekEnum.class);
                String[] weeklyArr = insPlanInfoVO.getWeekly().split(",");
                List<String> weeklyNames = new ArrayList<>();
                Arrays.asList(weeklyArr).forEach(week -> {
                    InsPlanWeekEnum weekEnum = all.stream().filter(a -> a.getValue().equals(Integer.valueOf(week))).findFirst().orElse(null);
                    if (weekEnum != null) {
                        weeklyNames.add(weekEnum.getName());
                    }
                });
                String weeklyName = weeklyNames.stream().collect(Collectors.joining(","));
                insPlanInfoVO.setWeeklyName(weeklyName);
            }
            return ConversionUtil.conversion(insPlanInfoVO, InsPlanInfoVO.class);
        }
        return null;
    }

    @Override
    public List<InsPlanAstPageVO> pagePlanAstList(InsPlanAstPageDto insPlanAstPageDto) {
        List<InsPlanAstPageVO> list = insPlanMapper.pagePlanAstList(insPlanAstPageDto);
        return ConversionUtil.conversionList(list, InsPlanAstPageVO.class);
    }

    @Override
    public List<InsPlanUnitPageVO> pagePlanUnitList(InsPlanUnitPageDto insPlanUnitPageDto) {
        List<InsPlanUnitPageVO> list = insPlanMapper.pagePlanUnitList(insPlanUnitPageDto);
        return ConversionUtil.conversionList(list, InsPlanUnitPageVO.class);
    }

    @Override
    public List<InsPlan> queryPlanTaskList() {
        List<InsPlan> planList = new ArrayList<>();
        List<InsPlan> astList = insPlanMapper.queryAstTaskList();
        List<InsPlan> unitList = insPlanMapper.queryUnitTaskList();
        planList.addAll(astList);
        planList.addAll(unitList);
        return planList;
    }

    /**
     * 新增巡检计划
     *
     * @param insPlan 巡检计划
     * @return 结果
     */
    @Override
    public int insertInsPlan(InsPlan insPlan) {
        insPlan.setCreateTime(LocalDateTime.now());
        return insPlanMapper.insertInsPlan(insPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addInsPlan(InsPlanAddDto insPlanAddDto) {
        InsPlan insPlan = new InsPlan();
        BeanUtils.copyProperties(insPlanAddDto, insPlan);
        //立即生效设置时间
        if (insPlan.getEffectiveType() != null && insPlan.getEffectiveType() == 1) {
            insPlan.setEffectiveStartDate(LocalDate.now());
            insPlan.setEffectiveEndDate(null);
        }
        insPlan.setCreateTime(LocalDateTime.now());
        insPlan.setUpdateTime(LocalDateTime.now());
        insPlanMapper.insertInsPlan(insPlan);
        Long planId = insPlan.getId();
        if (CollectionUtil.isNotEmpty(insPlanAddDto.getConfigItemIds())) {
            List<Long> configItemIds = insPlanAddDto.getConfigItemIds();
            List<InsPlanItem> insPlanItemList = new ArrayList<>();
            AtomicInteger index = new AtomicInteger(0);
            configItemIds.forEach(configItemId -> {
                InsPlanItem insPlanItem = new InsPlanItem();
                insPlanItem.setConfigItemId(configItemId);
                insPlanItem.setPlanId(planId);
                int sort = index.get() + 1;
                index.set(sort);
                insPlanItem.setSort(sort);
                insPlanItemList.add(insPlanItem);
            });
            insPlanItemService.saveBatch(insPlanItemList);
        }
        if (CollectionUtil.isNotEmpty(insPlanAddDto.getExecutionTimeList())) {
            List<InsPlanExecutionTimeDto> executionTimeAddList = insPlanAddDto.getExecutionTimeList();
            List<InsPlanExecutionTime> executionTimes = new ArrayList<>();
            AtomicInteger index = new AtomicInteger(0);
            executionTimeAddList.forEach(time -> {
                InsPlanExecutionTime executionTime1 = new InsPlanExecutionTime();
                executionTime1.setPlanId(planId);
                executionTime1.setStartTime(time.getStartTime());
                executionTime1.setEndTime(time.getEndTime());
                int sort = index.get() + 1;
                index.set(sort);
                executionTime1.setSort(sort);
                executionTimes.add(executionTime1);
            });
            insPlanExecutionTimeService.saveBatch(executionTimes);
        }
        // 生成立即生效任务
        if (insPlan.getEffectiveType().intValue() == EffectiveTypeEnum.INSTANTLY.getValue()) {
            insTaskJobService.createInsTaskByDate(insPlan, LocalDateTime.now());
        } else {
            // 在生效范围内 生成任务
            if (insPlan.getEffectiveStartDate()!=null&&insPlan.getEffectiveEndDate()!=null) {
                boolean isRange=InspectionTaskUtil.filterDate(insPlan.getEffectiveStartDate(),
                        insPlan.getEffectiveEndDate(),LocalDate.now());
                if(isRange){
                    insTaskJobService.createInsTaskByDate(insPlan, LocalDateTime.now());
                }
            }
        }
        return 1;
    }

    /**
     * 修改巡检计划
     *
     * @param insPlan 巡检计划
     * @return 结果
     */
    @Override
    public int updateInsPlan(InsPlan insPlan) {
        return insPlanMapper.updateInsPlan(insPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int editInsPlan(InsPlanEditDto insPlanEditDto) {
        InsPlan insPlan = new InsPlan();
        BeanUtils.copyProperties(insPlanEditDto, insPlan);
        //立即生效设置时间
        if (insPlan.getEffectiveType() != null && insPlan.getEffectiveType() == 1) {
            insPlan.setEffectiveStartDate(LocalDate.now());
            insPlan.setEffectiveEndDate(null);
        }
        insPlan.setUpdateTime(LocalDateTime.now());
        insPlanMapper.updateInsPlan(insPlan);
        Long planId = insPlan.getId();
        insPlanItemService.deleteByPlanId(planId);
        if (CollectionUtil.isNotEmpty(insPlanEditDto.getConfigItemIds())) {
            List<Long> configItemIds = insPlanEditDto.getConfigItemIds();
            List<InsPlanItem> insPlanItemList = new ArrayList<>();
            AtomicInteger index = new AtomicInteger(0);
            configItemIds.forEach(configItemId -> {
                InsPlanItem insPlanItem = new InsPlanItem();
                insPlanItem.setConfigItemId(configItemId);
                insPlanItem.setPlanId(planId);
                int sort = index.get() + 1;
                index.set(sort);
                insPlanItem.setSort(sort);
                insPlanItemList.add(insPlanItem);
            });
            insPlanItemService.saveBatch(insPlanItemList);
        }
        insPlanExecutionTimeService.deleteByPlanId(planId);
        if (CollectionUtil.isNotEmpty(insPlanEditDto.getExecutionTimeList())) {
            List<InsPlanExecutionTimeDto> executionTimeAddList = insPlanEditDto.getExecutionTimeList();
            List<InsPlanExecutionTime> executionTimes = new ArrayList<>();
            AtomicInteger index = new AtomicInteger(0);
            executionTimeAddList.forEach(time -> {
                InsPlanExecutionTime executionTime1 = new InsPlanExecutionTime();
                executionTime1.setPlanId(planId);
                executionTime1.setStartTime(time.getStartTime());
                executionTime1.setEndTime(time.getEndTime());
                int sort = index.get() + 1;
                index.set(sort);
                executionTime1.setSort(sort);
                executionTimes.add(executionTime1);
            });
            insPlanExecutionTimeService.saveBatch(executionTimes);
        }
        // 生成立即生效任务
        if (insPlan.getEffectiveType().intValue() == EffectiveTypeEnum.INSTANTLY.getValue()) {
            insTaskJobService.createInsTaskByDate(insPlan, LocalDateTime.now());
        } else {
            // 在生效范围内 生成任务
            if (insPlan.getEffectiveStartDate()!=null&&insPlan.getEffectiveEndDate()!=null) {
                boolean isRange=InspectionTaskUtil.filterDate(insPlan.getEffectiveStartDate(),
                        insPlan.getEffectiveEndDate(),LocalDate.now());
                if(isRange){
                    insTaskJobService.createInsTaskByDate(insPlan, LocalDateTime.now());
                }
            }
        }
        return 1;
    }

    @Override
    public int updateState(InsPlanStateDto insUnitPlanDto) {
        InsPlan insPlan = new InsPlan();
        insPlan.setId(insUnitPlanDto.getId());
        insPlan.setIsEnable(insUnitPlanDto.getIsEnable());
        return insPlanMapper.updateState(insPlan);
    }

    /**
     * 批量删除巡检计划
     *
     * @param ids 需要删除的巡检计划主键
     * @return 结果
     */
    @Override
    public int deleteInsPlanByIds(Long[] ids) {
        return insPlanMapper.deleteInsPlanByIds(ids);
    }

    /**
     * 删除巡检计划信息
     *
     * @param id 巡检计划主键
     * @return 结果
     */
    @Override
    public int deleteInsPlanById(Long id) {
        return insPlanMapper.deleteInsPlanById(id);
    }

    @Override
    public InsObjInfo getObjInfo(Long id) {
        return insPlanMapper.getObjInfo(id);
    }
}
